// see: https://github.com/grncdr/js-is-function/blob/master/index.js
const is_function = (fn) => {
  if (!fn) return false

  const string = Object.prototype.toString.call(fn)
  return string === '[object Function]' ||
    (typeof fn === 'function' && string !== '[object RegExp]') ||
    (typeof window !== 'undefined' &&
     // IE8 and below
     (fn === window.setTimeout ||
      fn === window.alert ||
      fn === window.confirm ||
      fn === window.prompt))
};

const is_number = (n) => typeof n === 'number' || n instanceof Number;

const is_symbol = (s) => typeof s === 'symbol';

const is_string = (s) => typeof s === 'string' || s instanceof String

const cons = (a, b) => (m) => m === 0 ? a : m === 1 ? b : 'Pair';

const car = (p) => p(0);

const cdr = (p) => p(1);

const is_pair = (p) => is_function(p) && p('type') === 'Pair'; // TODO: 如何实现类型识别


const to_string = (it) =>
  is_symbol(it) ? `${it.description}`
: is_string(it) ? JSON.stringify(it)
: is_pair(it)   ? `(${pair_to_string(it)})`
: `${it}`


function pair_to_string (p) {
  const first = car(p)
  const rest = cdr(p)

  if (rest === null) {
    return `${to_string(first)}`
  }
  if (is_pair(rest)) {
    return `${to_string(first)} ${pair_to_string(rest)}`
  }

  return `${to_string(first)}, ${to_string(rest)}`
}

const error = (msg) => {
  throw new Error(msg);
};

module.exports = {
  is_function,
  is_number,
  is_symbol,
  is_string,
  cons,
  car,
  cdr,
  is_pair,
  to_string,
  error,
};
